--桌子逻辑
local skynet = require "skynet"
local cluster = require "skynet.cluster"
local tabletool = require "tabletool"
local timetool = require "timetool"
local timer = require "timer"
local filelog = require "filelog"
local configdao = require "configdao"
local base = require "base"
local json = require "cjson"
json.encode_sparse_array(true, 1, 1)

require "cpcqsscenum"

local TableLogic = {}
local service = nil
local seatlogic = nil
local gamelogic = nil

function TableLogic.init(caller)
	service = caller
end

-- 在tablecmd:start 调用的
-- 这里的 tableobj，其实就是 table_data
-- conf 是从客户端传上来的, table_conf
--
function TableLogic.init_data(tableobj, conf, attachconf)
	-- 这里的两个logic 是tablelogic后面才加入进去的，所以没办法放到 init() 里面去初始化
	seatlogic = service:get_logicbyname("seatlogic")

	-- 获得游戏逻辑
	gamelogic = service:get_logicbyname("gamelogic")
	if conf == nil  then
		filelog.sys_error("TableLogic.init_data conf == nil", conf)
		return false
	end

    --初始化桌子信息
	local now = timetool.get_time()
    local nodename = skynet.getenv("nodename")
	tableobj.table_type = conf.table_type
	tableobj.uuid = nodename .. "_" .. attachconf.code .. "_" .. attachconf.index .. "_" .. now
	tableobj.index = attachconf.index
	tableobj.code = attachconf.code
	tableobj.state = ECQSSCTableState.TABLE_STATE_WAIT_PLAYER_SITDOWN
	tableobj.create_rid = attachconf.rid
	tableobj.create_rolename = attachconf.rolename
    tableobj.create_logo = attachconf.logo
	tableobj.create_time = now
	tableobj.cur_player_num = 0
	tableobj.curr_to_num = 0
	tableobj.conf = conf
    tableobj.cur_watch_playernum = 0
    tableobj.table_service = attachconf.table_service
    tableobj.sitdown_player_num = 0
    tableobj.table_persist = attachconf.table_persist        --桌子没人时，保留时间
    tableobj.tradeid = attachconf.tradeid
    tableobj.last_heart_time = now
    tableobj.level_type = attachconf.level_type or 1
    tableobj.min_player_num = 1             --桌子最小人数
    tableobj.max_history_record_num = 100   --保存的最大历史记录数量
    tableobj.service_fee_rate = 0.00    --服务费比率3%

    --设置最小携带量
    if not tableobj.conf.min_carry_amount or tableobj.conf.min_carry_amount < 0 then
        tableobj.conf.min_carry_amount = 0
    end

    --设置最大携带量
    if not tableobj.conf.max_carry_amount or tableobj.conf.max_carry_amount < 0 then
        tableobj.conf.max_carry_amount = 0
    end

    --设置最大玩家数
    tableobj.conf.max_player_num = tableobj.conf.max_player_num or 500

    --初始化倍率列表
    tableobj.odds_list = {}
    -- for _,v in pairs(tableobj.conf.odds_list) do
    --     local id = math.floor(v / 100)
    --     local odds = v % 100
    --     tableobj.odds_list[id] = odds
    -- end
    local odds_list_get = skynet.call(".slotmgr", "lua", "get_odds_list")
    tableobj.odds_list = odds_list_get
    --添加座位
	local seat
	local count = 1
	while count <= conf.max_player_num do
		seat = { }
        seatlogic.init_data(seat,count)
		table.insert(tableobj.seats, seat) --初始化座位数据
		count = count + 1
	end

    --初始游戏数据
	tableobj.gameobj = {tableobj = {}, stateevent = {}}
	gamelogic.init_data(tableobj.gameobj, tableobj)
    tableobj.last_points = {} 
    local now_time = timetool.get_time()
    local get_curr_qishu = skynet.call(".slotmgr", "lua", "get_curr_qishu_string", now_time)
    local get_last_qishu = skynet.call(".slotmgr", "lua", "get_last_qishu", now_time)
    local get_stop_bet_time = skynet.call(".slotmgr", "lua", "get_stop_bet_time", now_time)
    local open_award_time = skynet.call(".slotmgr", "lua", "get_open_award_time", get_stop_bet_time)
    ---filelog.sys_error("---------curr_qishu-----------", get_curr_qishu, get_last_qishu, os.date("%Y-%m-%d  %H:%M:%S", get_stop_bet_time))
    local curr_table = base.strsplit(get_last_qishu, "-")
    local curr_qihao = "" .. curr_table[1] .. curr_table[2]
    ---filelog.sys_error("----------curr_qihao------", curr_table, curr_qihao)

    skynet.fork(function()
        while #tableobj.last_points ~= 5 do
            tableobj.last_points = {}
            local get_result = skynet.call(".slotmgr", "lua", "get_lottery_result_by_qihao", curr_qihao)
            if get_result ~= false then
                local last_result = json.decode(get_result)
                if last_result and last_result.rows == 2 then
                    if curr_qihao == last_result.data.qihao then
                        local get_points = base.strsplit(last_result.data.data, ",")
                        if #get_points == 5 then
                            -- for index, point in ipairs(get_points) do
                            --     table.insert(tableobj.last_points, tonumber(point))
                            -- end
                            for i = 5,1,-1 do
                                table.insert(tableobj.last_points, tonumber(get_points[i]))
                            end
                            tableobj.last_points_qishu = get_last_qishu
                        end
                    end
                end
            end
            skynet.sleep(2 * 100)
        end 
    end)
    ----设置当前期数
    tableobj.cur_qishu = get_curr_qishu
    tableobj.last_cur_qishu = get_last_qishu
    tableobj.open_award_time = open_award_time
    tableobj.curr_qishu_stop_bet_time = get_stop_bet_time
    -- filelog.sys_error("-----------cur_qishu, last_cur_qishu, open_award_time, last_poins--------", tableobj.cur_qishu, tableobj.last_cur_qishu, 
    --         tableobj.open_award_time, tableobj.curr_qishu_stop_bet_time, tableobj.last_points)
    gamelogic.wait_player_sitdown(tableobj.gameobj)
    if now_time >= tableobj.curr_qishu_stop_bet_time and now_time < tableobj.open_award_time then
        ----切换到停止封盘状态
        filelog.sys_error("----------切换到封盘状态------------------")
        --一初始化游戏
        gamelogic.onegamestart_inittable(tableobj.gameobj) 
        --初始化游戏记录
        gamelogic.onegamestart_init_tablerecord(tableobj.gameobj)
        tableobj.state = ECQSSCTableState.TABLE_STATE_STOP_BET
    else
        tableobj.state = ECQSSCTableState.TABLE_STATE_GAME_START
    end
    gamelogic.run(tableobj.gameobj)
	return true
end

---------------------------------------------------------
--处理客户端请求
--

--
-- 进桌
-- 客户端进桌请求最终在这里处理
-- tableobj：桌子对象
-- request：请求包
-- seat： 座位对象，nil or 非nil，由此判断是否重进桌子？
--
function TableLogic.entertable(tableobj, rid, roledata, request, seat)
    local playerinfo = roledata.info or {}
    local playermoney = roledata.money or {}

    --处理重进桌子
	if seat then
		local noticemsg = {
			rid = seat.rid,
			seat_index = seat.index,	
		}
		TableLogic.sendmsg_to_tableplayer(seat.rid,"reentertableN", noticemsg)
		if not tableobj.is_had_start then
			if tableobj.delete_table_timer_id > 0 then
				timer.cleartimer(tableobj.delete_table_timer_id)
				tableobj.delete_table_timer_id = -1
			end
		end
	else    --新进入桌子

        --先加入等待玩家列表，并设置相关信息
		local waitinfo = tableobj.waits[rid]
        if waitinfo == nil then
			waitinfo = {}
			waitinfo.playerinfo = {}
			tableobj.waits[rid] = waitinfo
			tableobj.cur_watch_playernum = tableobj.cur_watch_playernum + 1			 
        end

		waitinfo.rid = rid
        waitinfo.playerinfo.coin = playermoney.coin
        waitinfo.playerinfo.diamond = playermoney.diamond
        waitinfo.is_robot = roledata.is_robot
        --暂不支持旁观，超过10s未坐下，则踢出
        if not waitinfo.watch_timer_id then
            waitinfo.watch_timer_id = 0
            local curmoney = TableLogic.get_curmoney(waitinfo)
            waitinfo.watch_timer_id = timer.settimer(10 * 100,"do_watch",{rid = rid, coin = curmoney})
        end
	end

    --如果正在删除桌子，停止删除
	if tableobj.delete_table_timer_id > 0 then
		timer.cleartimer(tableobj.delete_table_timer_id)
		tableobj.delete_table_timer_id = -1
	end
end

--
--坐下
--
function TableLogic.sitdowntable(tableobj, rid, request, seat, roledata)
    local playerinfo = roledata.info or {}
    local playermoney = roledata.money or {}

    --清空旁观超时计时器
    local waitinfo = tableobj.waits[rid] or {}
    if waitinfo.watch_timer_id and waitinfo.watch_timer_id > 0 then
        timer.cleartimer(waitinfo.watch_timer_id)
    end
    tableobj.waits[rid] = nil
    tableobj.cur_watch_playernum = tableobj.cur_watch_playernum - 1

    --初始化seat数据
	seat.rid = rid
	seat.playerinfo.rolename = playerinfo.rolename or ""
	seat.playerinfo.logo = playerinfo.logo or ""
	seat.playerinfo.sex = playerinfo.sex or 0
	seat.playerinfo.ip_addr = roledata.ip_addr or playerinfo.ip_addr
    seat.playerinfo.gps_addr = roledata.gps_addr or playerinfo.gps_addr
    seat.playerinfo.recommrid =  playerinfo.recommrid           --推荐人rid
	seat.playerinfo.agencyrid =  playerinfo.agencyrid           --代理rid
	seat.playerinfo.agencylevel =  playerinfo.agencylevel or 0  --代理等级，0表示不是代理
    seat.playerinfo.level = playerinfo.level or 0
    seat.playerinfo.intro = playerinfo.intro or ""
    seat.playerinfo.upvoted_num = playerinfo.upvoted_num
    seat.playerinfo.downvoted_num = playerinfo.downvoted_num
    seat.playerinfo.logoframe = playerinfo.logoframe

	seat.state = ECQSSCSeatState.SEAT_STATE_WAIT_READY
	seat.playerinfo.coin = playermoney.coin or 0
	seat.playerinfo.lock_coin = playermoney.lock_coin or 0
	seat.playerinfo.diamond = playermoney.diamond or 0
    seat.playerinfo.lock_diamond = playermoney.lock_diamond or 0
	seat.is_disconnected = false
    seat.is_robot = roledata.is_robot or false
    seat.cur_base_score = tableobj.conf.base_score_list[1] --默认选择第1个可选底注

    --未开局
    if not tableobj.is_had_start or tableobj.state == ECQSSCTableState.TABLE_STATE_WAIT_PLAYER_SITDOWN then
        tableobj.is_had_start = false
	    ---tableobj.state = ECQSSCTableState.TABLE_STATE_WAIT_ALL_READY
	    gamelogic.on_sitdown_table(tableobj.gameobj, seat)
    end

    seat.ready_to_time = seat.ready_to_time or 2        --测试
    seat.ready_timeout_time = timetool.get_time() + seat.ready_to_time

    --设置超时
    if not seat.ready_timer_id or seat.ready_timer_id == -1 then
        seat.ready_timer_id = 0
        seat.ready_timer_id = timer.settimer(seat.ready_to_time * 100,"doready",{seat_index = seat.index,rid = seat.rid})
    end
end

--
--- 准备
-- @param tableobj 牌桌对象
-- @param request 请求数据
-- @param seat 桌位对象
--
function TableLogic.gameready(tableobj, request, seat, roledata)
	local noticemsg = {
		rid = seat.rid,
		seat_index = seat.index,
		is_ready = false,
	}

	if seat.state == ECQSSCSeatState.SEAT_STATE_WAIT_START then 
		noticemsg.is_ready = true 
	end

    --已开局    
    if tableobj.is_had_start then
        if tableobj.is_ingame then  --游戏中
            seatlogic.onegamestart_initseat(seat)
            if tableobj.state == ECQSSCTableState.TABLE_STATE_WAIT_OPEN_DICE then    --下注中，则通知玩家下注
                seat.state = ECQSSCSeatState.SEAT_STATE_WAIT_BET
                --通知玩家下注
                local noticemsg = {
                    wait_action_type = ECQSSCActionType.ACTION_TYPE_BET,
                    action_timeout_time = tableobj.action_timeout_time - 1,
                }
                TableLogic.sendmsg_to_tableplayer(seat.rid, "todoN", noticemsg)
            elseif tableobj.state <= ECQSSCTableState.TABLE_STATE_WAIT_PLAYER_BET then    --等待下注中
                seat.state = ECQSSCSeatState.SEAT_STATE_WAIT_BET
            else
                seat.state = ECQSSCSeatState.SEAT_STATE_INGAME_WATCH     --游戏中旁观
            end
        else
            seat.state = ECQSSCSeatState.SEAT_STATE_WAIT_START
        end
        return
    end

    --未开始第一局
	local isallready = false
	local playernum = 0
	for k, v in pairs(tableobj.seats) do
		if not seatlogic.is_empty(v) then
			if v.had_ready then
                playernum = playernum + 1
				isallready = true
                break
			end
		end
	end

	-- if isallready and playernum >= tableobj.min_player_num
 --        and tableobj.state == ECQSSCTableState.TABLE_STATE_WAIT_ALL_READY then		
 --        tableobj.state = ECQSSCTableState.TABLE_STATE_GAME_START
	-- 	gamelogic.run(tableobj.gameobj)
	-- end
end

--
-- doaction操作
--
function TableLogic.doaction(tableobj, rid, request, seat)
	local action_type = request.action_type or 0
    local call_func = nil
    if action_type == ECQSSCActionType.ACTION_TYPE_BET then                   --下注
        call_func = TableLogic.do_bet
    else
        return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = "无效的操作类型"}
    end
    return call_func(tableobj, request, seat)
end


local function check_bet_item_ids(bet_item_ids)
    local is_alright = true
    if not bet_item_ids or #bet_item_ids == 0 then
        is_alright = false
        return is_alright
    end
    for _, bet_item_id in ipairs(bet_item_ids) do
        local is_notfind = true
        for _, item_id in pairs(ECQSSCBetBtnId) do
            if item_id == bet_item_id then is_notfind = false end
        end
        if is_notfind == true then is_alright = false break end
    end
    return is_alright
end
--
--下注
--
function TableLogic.do_bet(tableobj, request, seat)
    local base_score_list = tableobj.conf.base_score_list
    local bet_item_ids = request.bet_item_ids or 0
    local bet_score = request.bet_score or 0
    local bet_times = request.bet_times or 1
    
    if tableobj.state ~= ECQSSCTableState.TABLE_STATE_WAIT_STOP_BET then
        return {retcode = 0, retstr = ""}
    end

    --庄家自己不能下注
    if seat.index == tableobj.banker_seat_index then
        return {retcode = EErrCode.ERR_INVALID_REQUEST, retstr = "庄家不能下注"}
    end

    if #bet_item_ids == 0 then
        return {retcode = EErrCode.ERR_INVALID_REQUEST, retstr = "请选择投注区域"}
    end

    if not check_bet_item_ids(bet_item_ids) then
        return {retcode = EErrCode.ERR_INVALID_REQUEST, retstr = "投注区域不合法"}
    end

    --下注列表为空，则初始化
    if not seat.cur_bet_list then
        seat.cur_bet_list = TableLogic.gen_bet_list(tableobj)
        seat.cur_bet_cnt_list = seat.cur_bet_cnt_list or {}
        seat.cur_betcnt_inc_list = seat.cur_betcnt_inc_list or {}
    end

    --检测下注的合法性
    for _,base_score in pairs(base_score_list) do
        if base_score == bet_score then
            seat.cur_base_score = bet_score
            break
        end
    end

    for _, bet_item_id in pairs(bet_item_ids) do
        if not seat.cur_bet_list[bet_item_id] then
            return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = "无效的参数"}
        end
    end

    if not seat or bet_score ~= seat.cur_base_score then
        return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = "无效的参数"}
    end


    --检测钱是否够
    local money = TableLogic.get_curmoney(seat)
    local all_wantmoney = #bet_item_ids * bet_score * bet_times
    local total_bet = seat.cur_total_bet + all_wantmoney
    local end_money = money - total_bet
    if end_money < 0 or money < 10 * 100 then
        return {retcode = EErrCode.ERR_NOT_ENOUGH_DIAMOND, retstr = "您的余额不足"}
    end

    if tableobj.cur_total_player_bet_cnt[seat.rid] == nil then
        tableobj.cur_total_player_bet_cnt[seat.rid] = 0
    end

    if tableobj.cur_total_player_bet_cnt[seat.rid] >= tableobj.conf.total_bet_times then
        return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = "超过下注次数"}
    end

    --统计总下注值
    tableobj.cur_total_bet_num = tableobj.cur_total_bet_num + all_wantmoney

    --更新下注列表
    seat.cur_bet_cnt = seat.cur_bet_cnt + 1
    seat.cur_total_bet = (seat.cur_total_bet or 0) + all_wantmoney
    

    tableobj.cur_total_player_bet_cnt[seat.rid] = ( tableobj.cur_total_player_bet_cnt[seat.rid] or 0 ) + 1

    tableobj.all_player_betinfo[seat.rid] = tableobj.all_player_betinfo[seat.rid] or {}
    
    for _, bet_item_id in ipairs(bet_item_ids) do
        tableobj.all_player_betinfo[seat.rid][bet_item_id] = ( tableobj.all_player_betinfo[seat.rid][bet_item_id] or 0 )
            + bet_score * bet_times
        seat.cur_bet_list[bet_item_id] = ( seat.cur_bet_list[bet_item_id] or 0)  + bet_score * bet_times
        tableobj.cur_total_bet_list[bet_item_id] = ( tableobj.cur_total_bet_list[bet_item_id] or 0 ) + bet_score * bet_times
    end
    ----通知gate扣钱
    local rid_values = { }
    local change_value = - all_wantmoney
    if not seat.is_robot then
        rid_values[seat.rid] = {}
        rid_values[seat.rid].beginvalue = seat.playerinfo.diamond
        rid_values[seat.rid].value = change_value
        rid_values[seat.rid].endvalue = rid_values[seat.rid].beginvalue + rid_values[seat.rid].value
        rid_values[seat.rid].real_change = seat.curr_score
        rid_values[seat.rid].total_bet = seat.cur_total_bet
        rid_values[seat.rid].level = seat.playerinfo.level
    end

    --通知gate去扣费
    local status,comment = TableLogic.game_balance_diamond(rid_values)
    if not status then
        filelog.sys_error("game balance diamond failed!")
        return false
    else
        filelog.sys_info("game balance diamond ok!")
    end

    local save_status, save_result = skynet.pcall(skynet.call, ".openaward", "lua", "save_player_betinfo", tableobj.cur_qishu, seat.rid, tableobj.all_player_betinfo[seat.rid])
    seat.playerinfo.diamond = seat.playerinfo.diamond + change_value
    --通知金钱改变
    if true then
        local noticemsg = {money_change_list = {}}
        local item = {
            rid = seat.rid,
            money_type = EMoneyType.DIAMOND, 
            change_value = -all_wantmoney, 
            final_value = money - seat.cur_total_bet,
        }
        if TableLogic.is_cointable() then
            item.money_type = EMoneyType.COIN
        end
        table.insert(noticemsg.money_change_list,item)
        TableLogic.sendmsg_to_tableplayer(seat.rid,"moneychangeN",noticemsg)
    end
    return {action_type = request.action_type }
end
--
--主动离桌
--
function TableLogic.leavetable(tableobj, request, rid, curmoney)
    local leavetablemsg = {
        rid = rid,
		table_index = tableobj.index,
	}

    if tableobj.waits[rid] ~= nil then
		TableLogic.sendmsg_to_alltableplayer(tableobj, "leavetableN", leavetablemsg)
		tableobj.cur_watch_playernum = tableobj.cur_watch_playernum - 1
        --通知router,删除rid-table的映射,并通知gate
        if not tableobj.waits[rid].is_robot then
            skynet.send(".router","lua","leave_table",nil,rid,tableobj.index,curmoney)
        else
            skynet.send(".robotmgr", "lua", "delete_robot", rid)
        end
	end
    tableobj.waits[rid] = nil

    --桌子正在删除直接返回
	if tableobj.isdeleting then
		return
	end

    --重置桌子数据
    if tableobj.is_had_start then
        gamelogic.reset_tabledata(tableobj.gameobj)
    end

	if tableobj.is_had_start then
		if tableobj.sitdown_player_num <= 0 then
			if tableobj.delete_table_timer_id > 0 then
				timer.cleartimer(tableobj.delete_table_timer_id)
				tableobj.delete_table_timer_id = -1
			end
			if tableobj.delete_table_timer_id == -1 then
                tableobj.delete_table_timer_id = 0
                --tableobj.delete_table_timer_id = timer.settimer(100, "delete_table")
            end
		end
	else
		if tableobj.sitdown_player_num <= 0 and tableobj.cur_watch_playernum <= 0 then
			if tableobj.delete_table_timer_id > 0 then
				timer.cleartimer(tableobj.delete_table_timer_id)
				tableobj.delete_table_timer_id = -1
			end
			if tableobj.delete_table_timer_id == -1 then
                tableobj.delete_table_timer_id = 0
                --tableobj.delete_table_timer_id = timer.settimer(100, "delete_table")
            end
		end
	end
end

--
--- 被动离桌
-- @param tableobj
-- @param rid
-- @param is_leave
--被动离开桌子，使用该接口时玩家必须是在旁观中
--记住使用者如果循环遍历旁观队列一定要使用原队列的copy队列
--
function TableLogic.passive_leavetable(tableobj, rid, curmoney, is_leave, reason)
	local leavetablemsg = {
        rid = rid,
		table_index = tableobj.index,
        reason = reason,
	}

	if tableobj.waits[rid] ~= nil then
		TableLogic.sendmsg_to_alltableplayer(tableobj, "leavetableN", leavetablemsg)
		tableobj.cur_watch_playernum = tableobj.cur_watch_playernum - 1
        --通知router,删除rid-table的映射,并通知gate
        if not is_leave and not tableobj.waits[rid].is_robot then
            skynet.send(".router","lua","leave_table",nil,rid,tableobj.index,curmoney)
        end
        if tableobj.waits[rid].is_robot then
            skynet.send(".robotmgr", "lua", "delete_robot", rid)
        end
	end
	tableobj.waits[rid] = nil

    --桌子正在删除直接返回
	if tableobj.isdeleting then
		return
	end

    --重置桌子数据
    if tableobj.is_had_start then
        gamelogic.reset_tabledata(tableobj.gameobj)
    end

    --游戏已经开始
	if tableobj.is_had_start then
		if tableobj.sitdown_player_num <= 0 then
			if tableobj.delete_table_timer_id > 0 then
				timer.cleartimer(tableobj.delete_table_timer_id)
				tableobj.delete_table_timer_id = -1
			end
            if tableobj.delete_table_timer_id == -1 then
                tableobj.delete_table_timer_id = 0
                --tableobj.delete_table_timer_id = timer.settimer(100, "delete_table")
            end
		end
	else    --未开始，直接删除
		if tableobj.sitdown_player_num <= 0 and tableobj.cur_watch_playernum <= 0 then
			if tableobj.delete_table_timer_id > 0 then
				timer.cleartimer(tableobj.delete_table_timer_id)
				tableobj.delete_table_timer_id = -1
			end
			if tableobj.delete_table_timer_id == -1 then
                tableobj.delete_table_timer_id = 0
                --tableobj.delete_table_timer_id = timer.settimer(100, "delete_table")
            end
		end
	end
end

--
-- 被动站起
--
function TableLogic.passive_standuptable(tableobj, request, seat, reason, is_sendto_client)
    if seat.state == ECQSSCSeatState.SEAT_STATE_NO_PLAYER then
        return
    end

	tableobj.sitdown_player_num = tableobj.sitdown_player_num - 1 
	local standuptablemsg = {
		rid = seat.rid,
		seat_index = seat.index,
		table_index = tableobj.index,
        reason = reason,
	}
    seat.state = ECQSSCSeatState.SEAT_STATE_NO_PLAYER

    --保存进旁观列表
	if tableobj.waits[seat.rid] == nil then
		local waitinfo = {
			playerinfo = {},
		}
		tableobj.waits[seat.rid] = waitinfo
		waitinfo.rid = seat.rid
        waitinfo.playerinfo.coin = seat.playerinfo.coin
        waitinfo.playerinfo.diamond = seat.playerinfo.diamond
        waitinfo.is_robot = seat.is_robot
		tableobj.cur_watch_playernum = tableobj.cur_watch_playernum + 1
	end

	---
	--初始化座位数据
	gamelogic.standup_clear_seat(tableobj.gameobj, seat)
end

--
-- 主动站起
--
function TableLogic.standuptable(tableobj, request, seat)
    if seat.state == ECQSSCSeatState.SEAT_STATE_NO_PLAYER then
        return
    end

	tableobj.sitdown_player_num = tableobj.sitdown_player_num - 1
	local noticemsg = {
		rid = seat.rid, 
		seat_index = seat.index,
		table_index = tableobj.index,
		reason = EStandupReason.STANDUP_REASON_ONSTANDUP,
	}

	if tableobj.state == ECQSSCTableState.TABLE_STATE_UNKNOW then
		--TableLogic.sendmsg_to_tableplayer(seat.rid, "standuptableN", noticemsg)
	else
		--TableLogic.sendmsg_to_alltableplayer(tableobj, "standuptableN", noticemsg)
	end

    seat.state = ECQSSCSeatState.SEAT_STATE_NO_PLAYER
	if tableobj.waits[seat.rid] == nil then
		local waitinfo = {
			playerinfo = {},
		}
		tableobj.waits[seat.rid] = waitinfo
		waitinfo.rid = seat.rid
        waitinfo.playerinfo.coin = seat.playerinfo.coin
        waitinfo.playerinfo.diamond = seat.playerinfo.diamond
        waitinfo.is_robot = seat.is_robot
		tableobj.cur_watch_playernum = tableobj.cur_watch_playernum + 1
	end

	--初始化座位数据
	gamelogic.standup_clear_seat(tableobj.gameobj, seat)
end

--
--  所有玩家离桌
--
function TableLogic.leavetableallplayer(tableobj,reason)
    if type(tableobj.seats) ~= "table" then
        return
    end

	for _, seat in pairs(tableobj.seats) do
		if not seatlogic.is_empty(seat) then
            local rid,money = seat.rid,TableLogic.get_curmoney(seat)
			TableLogic.passive_standuptable(tableobj, nil, seat, reason)
			TableLogic.passive_leavetable(tableobj,rid,money)
		end
	end
end

--- 断线重连处理函数
-- @param tableobj
-- @param request
-- @param seat
--
function TableLogic.reentertable(tableobj, request, seat)
	local noticemsg
	local player_action
	local tmpseat
    local cur_player_action

    --更改断线状态
    if seat.is_disconnected then
	    seat.is_disconnected = false
    end

    --清除断线计时器
    if seat.disconnect_timer_id > 0 then
        timer.cleartimer(seat.disconnect_timer_id)
        seat.disconnect_timer_id = -1
    end

    --更改离开状态，通知所有玩家
	if seat.is_leave then
		seat.is_leave = false
		local noticemsg = {
			rid = seat.rid,
			seat_index = seat.index,	
		}
		TableLogic.sendmsg_to_tableplayer(seat.rid,"reentertableN", noticemsg)
	end

    --等待准备,则发送准备
	if tableobj.state == ECQSSCTableState.TABLE_STATE_WAIT_ALL_READY 
	and seat.state == ECQSSCSeatState.SEAT_STATE_WAIT_READY then
        --TableLogic.sendmsg_to_tableplayer(seat.rid, "doreadyN", {action_timeout_time = seat.ready_timeout_time})
        return
	end

    --摇骰子中，通知摇骰子
    if tableobj.state == ECQSSCTableState.TABLE_STATE_WAIT_PLAYER_BET then
        local banker_seat = tableobj.seats[tableobj.banker_seat_index] or tableobj.sys_banker_info
	    noticemsg = {
		    rid = banker_seat.rid,
		    seat_index = banker_seat.index,
		    dice_one = tableobj.dice_one,		
		    dice_two = tableobj.dice_two,
	    }
        TableLogic.sendmsg_to_tableplayer(seat.rid, "shakediceN", noticemsg)
        return
    end

    --下注中，则通知下注
    if tableobj.state == ECQSSCTableState.TABLE_STATE_WAIT_OPEN_DICE then
        noticemsg = {
            wait_action_type = ECQSSCActionType.ACTION_TYPE_BET,
            action_timeout_time = tableobj.action_timeout_time - 1,
        }
        TableLogic.sendmsg_to_tableplayer(seat.rid, "todoN", noticemsg)
        return
    end

    --开奖中，则通知开奖
    if tableobj.state == ECQSSCTableState.TABLE_STATE_WAIT_HANDLE_OPENCARD_RESULT then
        local rand_result = tableobj.rand_result_list or {}
        noticemsg = {
            player_cards = {},
            banker_cards = {},
            opencard_result = tabletool.deepcopy(tableobj.opencard_result),
        }
        for i = 1,4 do
            local all_result = rand_result.all_results[i] or {}
            local item = {
                cards = tabletool.deepcopy(rand_result.all_cards[i]), 
                cards_type = all_result.cards_type or 0, 
                points = all_result.points or 0,
            }
            if i == 1 then
                noticemsg.banker_cards = item
            else
                table.insert(noticemsg.player_cards,item)
            end
        end
        TableLogic.sendmsg_to_tableplayer(seat.rid, "opencardN", noticemsg)
        return
    end
end

--------------------------------------------
--send方法
--

--
-- 通知桌上所有玩家
--
function TableLogic.sendmsg_to_alltableplayer( tableobj, msgname, message)
    local retcode,retstr,msgbody
    if message and message.retcode  then
		retcode = tonumber(message.retcode)
		retstr = message.retstr or ""
		msgbody = message.msgbody or { }
    else
        msgbody = message
	end

    local rids = { }
    local seats = tableobj.seats
    for i,seat in pairs(seats) do
       if not seatlogic.is_empty(seat) 
       and not seat.is_disconnected 
       and not seat.is_robot then
            table.insert(rids,seat.rid)
       end 
    end

    if tableobj.waits ~= nil then
        for i,wait in pairs(tableobj.waits) do
            if not wait.is_robot then
                table.insert(rids,wait.rid)
            end
        end
    end
    
    service:send_notice_to_players(rids, msgname, msgbody, retcode, retstr)
end

--
-- 通知桌上除某玩家之外的所有玩家
-- rid 排除的玩家
--
function TableLogic.sendmsg_to_otheralltableplayer( tableobj,rid, msgname, message)
    local retcode,retstr,msgbody
    if message and message.retcode  then
		retcode = tonumber(message.retcode)
		retstr = message.retstr or ""
		msgbody = message.msgbody or { }
    else
        msgbody = message
	end

    local rids = { }
    local seats = tableobj.seats
    for i,seat in pairs(seats) do
       if not seatlogic.is_empty(seat) and seat.rid ~= rid and 
       not seat.is_disconnected and not seat.is_robot then
            table.insert(rids,seat.rid)
       end 
    end

     if tableobj.waits ~= nil then
        for i,wait in pairs(tableobj.waits) do
            if wait.rid ~= rid and not wait.is_robot then
                table.insert(rids,wait.rid)
            end
        end
    end
    
    service:send_notice_to_players(rids, msgname, msgbody, retcode, retstr)
end

--
-- 通知桌上某个玩家
--
function TableLogic.sendmsg_to_tableplayer( rid, msgname, message)
    local seat = TableLogic.get_seat_by_rid(service.table_data,rid) or {}
    if seat.is_disconnected or seat.is_robot then
        return
    end

    local retcode,retstr,msgbody
    if message and message.retcode  then
		retcode = tonumber(message.retcode)
		retstr = message.retstr or ""
		msgbody = message.msgbody or { }
    else
        msgbody = message
	end

    local rids = { }
    table.insert(rids,rid) 
    service:send_notice_to_players(rids, msgname, msgbody, retcode, retstr)
end

--
-- 通知所有旁观列表玩家
--

function TableLogic.sendmsg_to_allwaitplayer(tableobj, msgname, message)
    local retcode,retstr,msgbody
    if message and message.retcode  then
		retcode = tonumber(message.retcode)
		retstr = message.retstr or ""
		msgbody = message.msgbody or { }
    else
        msgbody = message
	end

    local rids = { }
    local waits = tableobj.waits
    for i,wait in pairs(waits) do
       if wait.rid and not wait.is_robot then
            table.insert(rids,wait.rid)
       end 
    end
    
    service:send_notice_to_players(rids, msgname, msgbody, retcode, retstr)
end

--
-- 更新桌子心跳时间
--
function TableLogic.update_table_heart_time(tableobj)
    tableobj.last_heart_time = timetool.get_time()
end

--
-- 设置所有座位状态
--
function TableLogic.setallseatstate(tableobj, state)
	for k,value in pairs(tableobj.seats) do
		value.state = state
	end
end


--------------------------------------------
--金钱相关

--
-- 结算后钻石信息，每局结算都要通知gate
-- rid_value {beginvalue,value,endvalue,rolename}
--
function TableLogic.game_balance_diamond(rid_values)
    local comment = TableLogic.create_comment()
    local status,result = skynet.pcall(cluster.call,"gatenode", ".router", "brgame_balance_diamond", rid_values, comment)
    if not status then
        filelog.sys_error("game_balance_diamond call failed!")
        return false
    else
        --记录流水日志
        local total_bet = 0
        local total_water = 0
        local sys_change = 0
        local total_change = 0
        for rid,item in pairs(rid_values) do
            total_water = total_water + math.abs(item.real_change or 0)
            total_bet = total_bet + (item.total_bet or 0)
            sys_change = sys_change + item.real_change
            total_change = total_change + item.value

            --记录下注值
            local bet_logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.DOBET, rid, item.level, 
            item.total_bet, 0, 0, 0, 0, 0, comment.table_uuid, comment.start_time, comment.table_tradeid)
            skynet.send(".diamondlog", "lua", "write", bet_logstr)
            --记录流水变化值
            local chg_logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.FUWUFEI, rid, item.level, item.real_change, 
            item.beginvalue,item.endvalue, 0, 0, 0, comment.table_uuid, comment.start_time, comment.table_tradeid)
            if item.real_change ~= 0 then
                skynet.send(".diamondlog", "lua", "write_file_redis", chg_logstr, rid)
            else
                skynet.send(".diamondlog", "lua", "write", chg_logstr)
            end
        end
        --记录系统的流水变化
        local logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.FUWUFEI, 0, 0, -sys_change, 0, 0, 0, 0, 0,
        comment.table_uuid, comment.start_time, comment.table_tradeid)
        skynet.send(".diamondlog", "lua", "write", logstr)

        --更新收益值,库存值，扣除抽水
        --local tableobj = service.table_data
        --local gamename =  TableLogic.get_gamename(tableobj)
        ---skynet.call(".slotmgr", "lua", "handle_balance_result", gamename, total_change, total_water, total_bet, comment)
    end
    return result,comment
end

--
--  改变金钱
--
function TableLogic.change_money(rid, itemvalues)
    local comment = TableLogic.create_comment()
    local status,result = skynet.pcall(cluster.call,"gatenode", ".router", "change_money", rid, itemvalues, comment)
    if not status then
        filelog.sys_error("change_money call failed!")
        return false
    end
    return result,comment
end

--------------------------------------------
--get方法
--

--
--根据rid获得座位对象
--
function TableLogic.get_seat_by_rid(tableobj, rid)
	if tableobj.seats == nil then
		return nil
	end

	for index, seat in pairs(tableobj.seats) do
		if rid == seat.rid then
			return seat
		end
	end
	return nil
end

--- 根据玩家的rid查找玩家是否在旁观队列
-- @param tableobj 牌桌对象
-- @param rid  玩家rid
function TableLogic.get_waitplayer_by_rid(tableobj, rid)
	for index, waitplayer in pairs(tableobj.waits) do
		if rid == waitplayer.rid then
			return waitplayer
		end
	end
	return nil
end

--
--- 根据指定桌位号获得一张空座位
-- @param tableobj 牌桌对象
-- @param index 座位号
function TableLogic.get_emptyseat_by_index(tableobj, index)
	if index == nil or index <= 0 or index > tableobj.conf.max_player_num then
		for index, seat in pairs(tableobj.seats) do
			if seatlogic.is_empty(seat) then
				return seat
			end
		end
	else
		local seat = tableobj.seats[index]
		if seatlogic.is_empty(seat) then
			return seat
		end
	end
	return nil
end

--
-- 获得桌子索引号
--
function TableLogic.get_table_index(tableobj)
	return tableobj.table_index
end

--
-- 获得坐下玩家数
--
function TableLogic.get_sitdown_player_num(tableobj)
	return tableobj.sitdown_player_num
end

--
-- 获得游戏中玩家数
--
function TableLogic.get_ingame_playernum(tableobj)
	local playernum = 0	
	for _, seat in pairs(tableobj.seats) do
		if gamelogic.is_ingame(tableobj.gameobj, seat) then
			playernum = playernum + 1
		end
	end
	return playernum
end

--------------------------------------------
--is方法
--

--- 判断当前桌子是否坐满
-- @param tableobj  牌桌对象
--
function TableLogic.is_full(tableobj)
	return (tableobj.sitdown_player_num >= tableobj.conf.max_player_num)
end

---判断当前是否能够开始游戏
-- @param tableobj	牌桌对象
--
function TableLogic.is_canstartgame(tableobj)
	return (tableobj.sitdown_player_num >= tableobj.min_player_num)
end

--- 判断游戏是否结束
-- @param tableobj 牌桌对象
--
function TableLogic.is_gameend(tableobj)
	if tableobj.state == ECQSSCTableState.TABLE_STATE_GAME_END
	or tableobj.state == ECQSSCTableState.TABLE_STATE_WAIT_PLAYER_SITDOWN
	or tableobj.state == ECQSSCTableState.TABLE_STATE_UNKNOW then
		return true
	end

	return false
end

--- 判断当前局是否已经结束游戏
-- @param tableobj 牌桌对象
--
function TableLogic.is_onegameend(tableobj)
	if tableobj.state == ECQSSCTableState.TABLE_STATE_ONE_GAME_REAL_END
	or tableobj.state == ECQSSCTableState.TABLE_STATE_WAIT_ALL_READY 
    or tableobj.state == ECQSSCTableState.TABLE_STATE_WAIT_ONE_GAME_START then
		return true
	end

	if not tableobj.is_ingame then
		return true
	end

	return TableLogic.is_gameend(tableobj)
end

--------------------------------------------
--copy方法
--

--
-- 这是要按照proto来组织，然后返回给客户端
--
function TableLogic.copy_table_gameinfo(self_index)
    local table_data = service.table_data
	local gameinfo = {}
	gameinfo.table_baseinfo = {}
    gameinfo.table_conf = {} tabletool.deepcopy(table_data.conf)
	gameinfo.seat_roleinfos = {}
	gameinfo.seat_gameinfos = {}

    --[[
    message table_conf {
        optional int32  table_type          = 1;        //类型 1：金币
        //通用设置  
        optional int32  max_player_num      = 2;        //桌子支持最大玩家数（旁观的不算）默认12人
        optional int32  is_public           = 3;        //是否公开，列表里可以看见（1:公开，0：私密好友）
        repeated int32  base_score_list     = 4;        //底注列表，形如：{10,100,500,5000}
        optional int32  min_carry_amount    = 5;        //最小携带量
        optional int32  max_carry_amount    = 6;        //最大携带量
        repeated int32  odds_list           = 7;        //赔率列表
        optional int32  each_bet_limit      = 8;        //每门下注上限
        optional int32  total_bet_limit         = 9;        //总下注上限
        optional int32  total_bet_times         = 10;       //一局总下注次数
        repeated int32  bet_btn_list            = 11;       //下注按钮列表
    }
    --]]
    gameinfo.table_conf.table_type = table_data.conf.table_type
    gameinfo.table_conf.max_player_num = table_data.conf.max_player_num
    gameinfo.table_conf.is_public = table_data.conf.is_public
    gameinfo.table_conf.base_score_list = table_data.conf.base_score_list
    gameinfo.table_conf.min_carry_amount =table_data.conf.min_carry_amount
    gameinfo.table_conf.max_carry_amount =table_data.conf.max_carry_amount
    gameinfo.table_conf.odds_list        =table_data.conf.odds_list
    gameinfo.table_conf.each_bet_limit   =table_data.conf.each_bet_limit
    gameinfo.table_conf.total_bet_limit  =table_data.conf.total_bet_limit
    gameinfo.table_conf.total_bet_times  =table_data.conf.total_bet_times
    gameinfo.table_conf.bet_btn_list     =table_data.conf.bet_btn_list

    --[[
    //桌子的基本相关信息
    message table_baseinfo{
        optional int32  table_type          = 1;            //这里和 table_conf 里面重合，是为了使用方便
        optional string uuid                = 2;            //桌子的唯一id，nodename_timenow_code，查看大战绩时也可以使用
        optional int32  index               = 3;            //桌子在table中的序列号 ,这里用的id，就是index
        optional int32  code                = 4;            //随机桌号,客户端也显示成房间号
        optional int32  state               = 5;            //状态（准备， 玩牌
        optional int32  bet_stop_time       = 6;            //下注截止时间
        optional string cur_qishu           = 7;            //当期期数
        repeated int32  last_open_points    = 8;            //上一期开奖结果
        optional int32  last_open_time      = 9;            //上期开奖时间
        optional string last_qishu          = 10;           //上期期数
    }
    --]]
    gameinfo.table_baseinfo.table_type = table_data.conf.table_type
	gameinfo.table_baseinfo.uuid = table_data.uuid 
	gameinfo.table_baseinfo.index = table_data.index 
	gameinfo.table_baseinfo.code = table_data.code 
	gameinfo.table_baseinfo.state = table_data.state
    ---gameinfo.table_baseinfo.bet_stop_time = table_data.curr_qishu_stop_bet_time or 0
    gameinfo.table_baseinfo.bet_stop_time = table_data.curr_qishu_stop_bet_time or 0
    if not table_data.cur_qishu or table_data.cur_qishu == "" then
        local nowtime = timetool.get_time()
        gameinfo.table_baseinfo.cur_qishu = "" .. os.date("%Y%m%d", nowtime) .. "-" .. tostring(table_data.curr_to_num)
    else
        gameinfo.table_baseinfo.cur_qishu = table_data.cur_qishu
    end 
    
    if not table_data.all_player_historys or #table_data.all_player_historys == 0 then
        if not table_data.last_cur_qishu or table_data.last_cur_qishu == "" then
            gameinfo.table_baseinfo.last_qishu = ""
        else
            gameinfo.table_baseinfo.last_qishu = table_data.last_cur_qishu
        end
        if not table_data.last_points or #table_data.last_points ~= 5 then
            gameinfo.table_baseinfo.last_open_points = {}
        else
            if table_data.last_cur_qishu == table_data.last_points_qishu then
                gameinfo.table_baseinfo.last_open_points = table_data.last_points
            else
                gameinfo.table_baseinfo.last_open_points = {}
            end
        end
        gameinfo.table_baseinfo.last_open_time = 0
    else
        local lastrecord = table_data.all_player_historys[#table_data.all_player_historys]
        if lastrecord then
            if table_data.last_cur_qishu == lastrecord.open_qishu then
                gameinfo.table_baseinfo.last_open_points = lastrecord.points
                gameinfo.table_baseinfo.last_open_time = lastrecord.open_award_time
                gameinfo.table_baseinfo.last_qishu = lastrecord.open_qishu
            else
                gameinfo.table_baseinfo.last_open_points = {}
                gameinfo.table_baseinfo.last_open_time = 0
                gameinfo.table_baseinfo.last_qishu = table_data.last_cur_qishu
            end
        else
            gameinfo.table_baseinfo.last_open_points = {}
            gameinfo.table_baseinfo.last_open_time = 0
            gameinfo.table_baseinfo.last_qishu = ""
        end
    end
    
    --拷贝座位信息
    local all_seats_info = TableLogic.copy_all_seats_info(self_index)
    gameinfo.seat_roleinfos = all_seats_info.seat_roleinfos
    gameinfo.seat_gameinfos = all_seats_info.seat_gameinfos
	return gameinfo
end

--
--拷贝所有座位信息
--
function TableLogic.copy_all_seats_info(self_index)
    local tableobj = service.table_data
    local all_seats_info = {seat_roleinfos = {}, seat_gameinfos = {}}

    --拷贝自己的信息
    if tableobj.seats[self_index] then
        local self_seat = tableobj.seats[self_index]
        all_seats_info.seat_roleinfos = TableLogic.copy_seat_roleinfo(self_seat)
		all_seats_info.seat_gameinfos = TableLogic.copy_seat_gameinfo(self_seat)
        all_seats_info.seat_gameinfos.index = idx
    end

    return all_seats_info
end

--
--拷贝座位游戏信息
--
function TableLogic.copy_seat_gameinfo(seat, is_limit)
    --[[
    message betitem{
        optional int32 bet_id = 1;  //下注区域id
        optional int32 bet_num = 2; //下注金额
    }
    //座位上和游戏相关的信息，随着游戏的进行，会进行变化的，包括钻石
    message seat_gameinfo {
        optional int32 rid         = 1;
        optional int32 index       = 2;             //位置座位编号
        optional int32 state       = 3;             //等待准备，等待开局，游戏中
        optional int32 offline     = 4;             //1断线，0在线
        optional int32 cur_money   = 5;             //当前金钱数
        optional int32 cur_total_bet = 6;           //当前总下注金额 = 每门下注金额之和
        optional int32 cur_base_score = 7;          //当前底注
        repeated betitem betitems  = 8; 
    }
    --]]
    local seat_gameinfo ={}
    seat_gameinfo.rid		= seat.rid
    seat_gameinfo.index		= seat.index
    seat_gameinfo.state     = seat.state
    seat_gameinfo.offline   = (seat.is_disconnected and 1) or 0
    seat_gameinfo.cur_money	= TableLogic.get_curmoney(seat)
    seat_gameinfo.cur_total_bet = seat.cur_total_bet
    seat_gameinfo.cur_base_score = seat.cur_base_score
    seat_gameinfo.betitems = {}
    ----获取玩家下过的注
    return seat_gameinfo
end

--
--拷贝座位角色信息
--
function TableLogic.copy_seat_roleinfo(seat, is_limit)
    --[[
    //座位玩家基本信息，显示在牌桌上的，不会变的
    message seat_roleinfo {
        optional int32 rid      = 1;
        optional string rolename = 2;
        optional string logo    = 3;
        optional int32 sex      = 4;
        optional int32 coin     = 5;
        optional int32 diamond  = 6;
        optional int32 fangka   = 7;
        optional string intro    = 8;       //个人信息
        optional string ip_addr     = 9;    //登录IP地址
        optional string gps_addr    = 10;   //玩家位置信息
        optional int32 upvoted_num  =  11;  //被赞数
        optional int32 downvoted_num = 12;  //被踩数
        optional int32 logoframe     = 13;  //头像框
    }
    --]]

    local seat_roleinfo = {}
    seat_roleinfo.rid = seat.rid
    seat_roleinfo.rolename = seat.playerinfo.rolename
    seat_roleinfo.logo = seat.playerinfo.logo
    seat_roleinfo.diamond = seat.playerinfo.diamond
    seat_roleinfo.sex = seat.playerinfo.sex
    seat_roleinfo.coin = seat.playerinfo.coin
    seat_roleinfo.fangka = 0
    seat_roleinfo.intro = seat.playerinfo.intro
    seat_roleinfo.ip_addr = seat.playerinfo.ip_addr
    seat_roleinfo.gps_addr = seat.playerinfo.gps_addr
    seat_roleinfo.upvoted_num = seat.playerinfo.upvoted_num
    seat_roleinfo.downvoted_num = seat.playerinfo.downvoted_num
    seat_roleinfo.logoframe = seat.playerinfo.logoframe
    return seat_roleinfo
end

------------------------------------------------
--其他

--清空桌子对象数据
--
function TableLogic.clear(tableobj)
	if tableobj.timer_id > 0 then
		timer.cleartimer(tableobj.timer_id)
		tableobj.timer_id = -1
	end

	if tableobj.delete_table_timer_id > 0 then
		timer.cleartimer(tableobj.delete_table_timer_id)
		tableobj.delete_table_timer_id = -1
	end

	for k,v in pairs(tableobj) do
		tableobj[k] = nil
	end
end

--
--创建comment
--
function  TableLogic.create_comment()
    local tableobj = service.table_data
    local tradeid = skynet.call(".nodeuuid", "lua", "getuuid")
    local start_time = tableobj.one_start_time or 0
   
    return {table_uuid = tableobj.uuid ,table_tradeid = tradeid,start_time = start_time,jackpot_id = tableobj.cur_jackpot_id}
end

--
--断开连接(断线）
--
function TableLogic.disconnect(tableobj, request, seat)
	seat.is_disconnected = true
	seat.is_leave = true
	local noticemsg = {
		rid = seat.rid,
		seat_index = seat.index,	
	}

	TableLogic.sendmsg_to_tableplayer(seat.rid,"disconnectN", noticemsg)

    --断线60s后，将其踢出
    if seat.disconnect_timer_id == -1 then
        seat.disconnect_timer_id = 0
        seat.disconnect_timer_id = timer.settimer(60 * 100, "disconnect_outtime", {index = seat.index})
    end

    if tableobj.state == ECQSSCTableState.TABLE_STATE_WAIT_ALL_READY 
    and seat.state == ECQSSCSeatState.SEAT_STATE_WAIT_READY then
        local rid,money = seat.rid,TableLogic.get_curmoney(seat)
        TableLogic.passive_standuptable(tableobj, {}, seat, EStandupReason.STANDUP_REASON_DISCONNECTED)	
        TableLogic.passive_leavetable(tableobj,rid,money)
    end
end

--
--生成一个下注列表
--
function TableLogic.gen_bet_list(tableobj)
    local bet_btn_list = tableobj.conf.bet_btn_list
    local new_bet_list = {}
    for _,id in pairs(bet_btn_list) do
        new_bet_list[id] = 0
    end
    
    return new_bet_list
end

------------------------------------------------------------------------
------------------------------------------------------------------------

--- 保存牌桌每局记录
-- @param game_records 游戏记录
--
function TableLogic.save_table_records(game_records)
    if not game_records.user_count or game_records.user_count <= 0 then
        return
    end
    local tableobj = service.table_data
    local tablerecords = {}

    tablerecords.user_count = game_records.user_count                       --游戏总人数
    tablerecords.sys_diamond_start = game_records.sys_diamond_start         --系统开始元宝
    tablerecords.sys_diamond_end = game_records.sys_diamond_end             --系统结束元宝
    tablerecords.sys_get_diamond = tableobj.cur_total_bet_num
    tablerecords.sys_peijiang_diamond = tableobj.sys_peijiang
    tablerecords.sys_all_service_fee = tableobj.all_service_fee
    tablerecords.begin_time = game_records.one_start_time                   --本局开始时间
    tablerecords.end_time = game_records.one_end_time                       --本局结束时间
    tablerecords.game_type = skynet.getenv("nodename")                      --游戏类型
    tablerecords.room_num = game_records.table_code                         --房间号
    tablerecords.game_info = game_records.players_balance_list              --玩家结算信息
    tablerecords.opencard_result = game_records.opencard_result             --开牌结果
    tablerecords = json.encode(tablerecords)

    --调用日志服务写到文件
	skynet.send(".tablerecordlog", "lua", "write",game_records.cur_record_id, tablerecords)
end

--- 保存牌桌最终记录(桌子被删除时）
-- @param tableobj 桌子对象
--
function TableLogic.save_table_final_records(tableobj)
    local game_records = tableobj.game_records

    local tablerecords = ""
	tablerecords = tablerecords .. game_records.table_uuid .. "_"           --桌子唯一id
    tablerecords = tablerecords .. game_records.table_type .. "_"           --桌子类型
	tablerecords = tablerecords .. game_records.create_user_rid .. "_"      --创建者rid
	tablerecords = tablerecords .. game_records.create_time .. "_"          --创建时间
    tablerecords = tablerecords .. game_records.delete_time .. "_"          --删除时间
	tablerecords = tablerecords .. game_records.start_time .. "_"           --第一局开始时间
    tablerecords = tablerecords .. game_records.end_time .. "_"             --最后一局结束时间
    tablerecords = tablerecords .. game_records.final_to_num .. "_"         --最终局数
    tablerecords = tablerecords .. game_records.delete_reason or 0          --删除原因
    
    --调用日志服务写到文件
	skynet.send(".gametablelog", "lua", "write",tablerecords)
end

--
--创建系统庄家
--
function TableLogic.gen_system_banker_info(tableobj)
    local banker_info = {}
    seatlogic.init_data(banker_info, -1)
    banker_info.rid = -1
    banker_info.real_rid = -1
    banker_info.is_banker = true
    banker_info.playerinfo.rolename = "小苏苏"
    banker_info.playerinfo.logo = "avator_71.jpg"
    banker_info.playerinfo.sex = 1
    banker_info.playerinfo.index = -1
    banker_info.playerinfo.coin = 500000
    banker_info.playerinfo.diamond = 500000
    banker_info.dobanker_round_num = 0   --做庄局数
    banker_info.last_win_score = 0       --上局输赢

    --从机器人节点获取系统庄信息
    local robotinfo = skynet.call(".robotmgr", "lua", "gen_system_banker_info")
    if robotinfo then
        banker_info.real_rid = robotinfo.rid
        banker_info.playerinfo.sex = robotinfo.sex
        banker_info.playerinfo.logo = robotinfo.logo
        banker_info.playerinfo.rolename = robotinfo.rolename
        banker_info.playerinfo.ip_addr = robotinfo.ip_addr
        banker_info.playerinfo.gps_addr = robotinfo.gps_addr
    end

    return banker_info
end

--
--获取游戏名（包括桌子类型)
--
function TableLogic.get_gamename(tableobj)
    local gamename = "cpcqssc"
    if tableobj.table_type == ECQSSCTableType.TABLE_TYPE_COIN then
        gamename = gamename .. "_coin"
    elseif tableobj.table_type == ECQSSCTableType.TABLE_TYPE_DIAMOND then
        gamename = gamename .. "_diamond"
    end
    return gamename
end

--
--获得当前代币数
--
function TableLogic.get_curmoney(seat)
    if not seat or not seat.playerinfo then
        return 0
    end

    local tableobj = service.table_data
    if tableobj.table_type == ECQSSCTableType.TABLE_TYPE_DIAMOND then
        return (seat.playerinfo.diamond or 0)
    elseif tableobj.table_type == ECQSSCTableType.TABLE_TYPE_COIN then
        return (seat.playerinfo.coin or 0)
    end
    return 0
end

--
--是否是金币桌
--
function TableLogic.is_cointable()
    if service.table_data.table_type == ECQSSCTableType.TABLE_TYPE_COIN then
        return true
    end
    return false
end

--
--是否是钻石桌
--
function TableLogic.is_diamondtable()
    if service.table_data.table_type == ECQSSCTableType.TABLE_TYPE_DIAMOND then
        return true
    end
    return false
end

--
--发送跑马灯
--
function TableLogic.send_horseracelamp(rolename, get_num)
	local horseconf = configdao.get_common_conf("horselampconf")
	if not horseconf or not horseconf[1] then return end
	local formatname = string.format(ELAMPCOLOR.GREEN, rolename)
	local formatnum = string.format(ELAMPCOLOR.RED, tostring(get_num))
	local horsestring = string.format(horseconf[1], formatname, EGameName, formatnum)
	skynet.pcall(cluster.send, "gatenode", ".router", "addpopmessage", horsestring)
end

--
--发送聊天消息
--
function TableLogic.send_tablechat(table_index, talkrid, msgbody, is_nodealy)
    if not is_nodealy then
        local delay = base.get_random(1,3)
        skynet.sleep(delay * 100)
    end
    skynet.pcall(cluster.send, "gatenode", ".router", "robot_tablechat", "cpcqssc", table_index, talkrid, msgbody)
end

function TableLogic.send_mail_to_player(rid, fields)
    service:send_mail_to_player(rid, fields)
end

function TableLogic.send_diamond_to_givesystem(rid, fields)
    service:send_diamond_to_givesystem(rid, fields)
end

function TableLogic.getbetrecord(rid)
    local tableobj = service.table_data
    local all_betrecords = {}
    if not rid or rid == 0 then
        return all_betrecords
    end
    for index, onerecord in ipairs(tableobj.all_player_historys) do
        for betrid, betdetail in pairs(onerecord.bet_info) do
            if rid == betrid then
                --[[
                    optional string qishu = 1;      //期数
                    optional int32  open_time = 2;  //开奖时间
                    repeated int32  prize_ids = 3;  //中奖的区域id
                    repeated int32  points = 4;     //开奖点数
                    optional int32  get_money_num = 5; //中奖金额(0 为未中奖)
                    repeated betdetail bet_infos = 6;  //玩家下注详情
                ]]
                local onebetrecord = {
                    qishu = onerecord.open_qishu,
                    open_time = onerecord.open_award_time,
                    prize_ids = onerecord.prize_ids,
                    points = onerecord.points,
                    get_money_num = 0,
                    bet_infos = {},
                }
                for bet_item_id, bet_num in pairs(betdetail) do
                    local onebet = {
                        bet_item_id = bet_item_id,
                        bet_num = bet_num,
                    }
                    table.insert(onebetrecord.bet_infos, onebet)
                end
                if onerecord.player_get_info[betrid] then
                    if onerecord.player_get_info[betrid].real_change > 0 then
                        onebetrecord.get_money_num = onerecord.player_get_info[betrid].real_change
                    else
                        onebetrecord.get_money_num = -1
                    end
                end
                table.insert(all_betrecords, onebetrecord)
            end
        end
        local cur_qishu = onerecord.open_qishu
        if tableobj.opening_betinfo[cur_qishu] ~= nil then
            tableobj.opening_betinfo[cur_qishu] = nil
        end
    end
    ---还在开奖中的
    for qishu, object in pairs(tableobj.opening_betinfo) do
        for betrid, betdetail in pairs(object.all_player_betinfo) do
            if rid == betrid then
                local onebetrecord = {
                    qishu = object.qishu,
                    open_time = 0,
                    prize_ids = {},
                    points = {},
                    get_money_num = 0,
                    bet_infos = {},
                }
                for bet_item_id, bet_num in pairs(betdetail) do
                    local onebet = {
                        bet_item_id = bet_item_id,
                        bet_num = bet_num,
                    }
                    table.insert(onebetrecord.bet_infos, onebet)
                end
                table.insert(all_betrecords, onebetrecord)
            end
        end
    end


    ---当前这期的还没开奖的
    if tableobj.all_player_betinfo[rid] then
        local onebetrecord = {
            qishu = tableobj.cur_qishu,
            open_time = 0,
            prize_ids = {},
            points = {},
            get_money_num = 0,
            bet_infos = {},
        }
        for bet_item_id, bet_num in pairs(tableobj.all_player_betinfo[rid]) do
            local onebet = {
                bet_item_id = bet_item_id,
                bet_num = bet_num,
            }
            table.insert(onebetrecord.bet_infos, onebet)
        end
        table.insert(all_betrecords, onebetrecord)
    end
    ---filelog.sys_error("------all_betrecords------", rid, all_betrecords)
    return all_betrecords
end

return TableLogic